package cn.hxth.cloud.provider.service.impl;

import cn.hxth.cloud.api.common.constant.OrderInfoStatus;
import cn.hxth.cloud.api.common.constant.ProcedureStatus;
import cn.hxth.cloud.api.common.util.AbstractBaseServiceImpl;
import cn.hxth.cloud.api.common.util.DateProvider;
import cn.hxth.cloud.api.domain.*;
import cn.hxth.cloud.api.mapper.OrderInfoItemMapper;
import cn.hxth.cloud.api.mapper.OrderInfoMapper;
import cn.hxth.cloud.api.mapper.ProductionOrderMapper;
import cn.hxth.cloud.api.mapper.SteelsMapper;
import cn.hxth.cloud.api.rabbitmq.RabbitMQSender;
import cn.hxth.cloud.provider.service.InventoryService;
import cn.hxth.cloud.provider.updater.ProductUpdater;
import cn.hxth.cloud.provider.updater.ProductUpdaterFactory;
import cn.hxth.cloud.provider.updater.SteelsUpdater;
import cn.hxth.cloud.provider.updater.SteelsUpdaterFactory;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@Service
public class InventoryServiceImpl extends AbstractBaseServiceImpl implements InventoryService {
    private final Logger logger = LoggerFactory.getLogger(InventoryServiceImpl.class);
    @Resource
    private ProductUpdaterFactory<OrderInfo> productUpdaterFactory;
    @Autowired
    private SteelsUpdaterFactory<SteelsInputOrder> steelsInputOrderSteelsUpdaterFactory;
    @Autowired
    private  ProductUpdaterFactory<ProductInputOrder> productInputOrderProductUpdaterFactory ;
    @Autowired
    private SteelsMapper steelsMapper;
    @Autowired
    private ProductionOrderMapper productionOrderMapper ;
    @Autowired
    private OrderInfoMapper orderInfoMapper ;
    @Autowired
    private OrderInfoItemMapper orderInfoItemMapper ;
    @Autowired
    private  ProductUpdaterFactory<ProductOutputOrder> productOutputOrderProductUpdaterFactory ;
@Autowired
    public InventoryServiceImpl(RabbitMQSender rabbitMQSender, RedisTemplate<String, String> redisTemplate, DateProvider dateProvider) {
        super(rabbitMQSender, redisTemplate, dateProvider);
    }

    @Override
    public Boolean updateProductInventoryForOrder(OrderInfo orderInfo) {
        try {
            ProductUpdater productUpdater = productUpdaterFactory.create(orderInfo);
            productUpdater.updateProduct();
        } catch (Exception e) {
            logger.error("error", e);
            return false;
        }
        return true;
    }

    @Override
    public Boolean updateProductOutputInventory(ProductOutputOrder productOutputOrder) {
        try{
            OrderInfo orderInfo = productOutputOrder.getOrderInfo();


            ProductUpdater productUpdater = productOutputOrderProductUpdaterFactory.create(productOutputOrder);
            productUpdater.updateProduct();

            if(!OrderInfoStatus.DELIVERED.equals(orderInfo.getStatus())){
                orderInfo.setStatus(OrderInfoStatus.DELIVERED);
                this.redisTemplate.delete("productOutputOrder_"+orderInfo.getId());

                sendMessage("order",orderInfo,"updateOrderStatus",null);

            }
        }catch (Exception e){
            logger.error("error",e);
            return  false ;
        }
        return  true ;

    }

    public Boolean updateSteelsInventoryForOrder(List<ProductionOrder> productionOrders) {
        Integer count = 0;
        for (ProductionOrder productionOrder : productionOrders) {
            Steels steels = productionOrder.getSteels();
            steels.setLockedInventory(steels.getLockedInventory() + productionOrder.getSteelsCount());
            Example example = new Example(Steels.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("id", productionOrder.getSid());
            example.excludeProperties("lockedInventory");
            count += this.steelsMapper.updateByExampleSelective(steels, example);
        }
        return count > 0;


    }
    public Boolean updateSteelsOutputInventory(SteelsOutputOrder steelsOutputOrder) {
        Integer count = 0;

        Steels steels = steelsMapper.selectByPrimaryKey(steelsOutputOrder.getSid()) ;
            if(steelsOutputOrder.getProductionOrder().getProcedureStatus()== ProcedureStatus.STOCKING)
            steels.setLockedInventory(steels.getLockedInventory() - steelsOutputOrder.getCount());
             steels.setInventory(steels.getInventory() - steelsOutputOrder.getCount());
            Example example = new Example(Steels.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("id", steelsOutputOrder.getSid());
            example.excludeProperties("lockedInventory", "inventory");
            count  = this.steelsMapper.updateByExampleSelective(steels, example);

        if(count > 0){
            ProductionOrder productionOrder = steelsOutputOrder.getProductionOrder();
            try {
                super.sendMessage("production",productionOrder,"updateProductionStatus",null);
            } catch (Exception e) {
                return  false ;
            }
        }
        return  count >0 ;


    }

    @Override
    public Boolean updateProductInputInventory(ProductInputOrder productInputOrder) {
       try{
          /* OrderInfo orderInfo = productOutputOrder.getOrderInfo();*/
          /* String jsonData = this.redisTemplate.opsForValue().get("productOutputOrder_" + orderInfo.getId());
           List<ProductOutputOrderItem> productOutputOrderItems = JSONObject.parseArray(jsonData, ProductOutputOrderItem.class);
           productOutputOrder.getProductOutputOrderItems().addAll(productOutputOrderItems) ;*/
           ProductUpdater productUpdater = productInputOrderProductUpdaterFactory.create(productInputOrder);
           productUpdater.updateProduct();
           List<Long> list = orderInfoItemMapper.findOid();
           for(Long id:list){
               ProductOutputOrder productOutputOrder = new ProductOutputOrder() ;
               productOutputOrder.setMakeDate(dateProvider.getCurrentTime());
               productOutputOrder.setOid(id);
               String jsonData = this.redisTemplate.opsForValue().get("productOutputOrder_" + productOutputOrder.getOid());
               if (jsonData == null){
                   List<ProductOutputOrderItem> productOutputOrderItems = JSONObject.parseArray(jsonData, ProductOutputOrderItem.class);
                   productOutputOrder.setProductOutputOrderItems(productOutputOrderItems); ;
               }
               super.sendMessage("wms",productOutputOrder,"insertProductOutputOrder",null);
           }
           /*if(orderInfoItemList.size()>0){
               List<ProductOutputOrderItem> productOutputOrderItemList = new ArrayList<>() ;
               ProductOutputOrder productOutputOrder = new ProductOutputOrder() ;
               productOutputOrder.setMakeDate(dateProvider.getCurrentTime());
               for(OrderInfoItem item:orderInfoItemList){
                   if(productOutputOrder.getOid() == null){
                       productOutputOrder.setOid(item.getOid());
                   }
                   ProductOutputOrderItem productOutputOrderItem = new ProductOutputOrderItem() ;
                   productOutputOrderItem.setCount(or);


               }
               productOutputOrder.setProductOutputOrderItems();

           }*/
       }catch (Exception e){
           logger.error("error",e);
           return  false ;
       }
       return  true ;
    }

    public  Boolean updateSteelsInputInventory(SteelsInputOrder steelsInputOrder){
        SteelsUpdater steelsUpdater = this.steelsInputOrderSteelsUpdaterFactory.create(steelsInputOrder);

        Boolean flag = steelsUpdater.updateSteels();

  if (flag){
      List<Long> ids = productionOrderMapper.findId();
      for(Long id:ids){
          String jsonStr = redisTemplate.opsForValue().get("steelsOutputOrder_" + id);
          SteelsOutputOrder steelsOutputOrder = JSONObject.parseObject(jsonStr,SteelsOutputOrder.class) ;
          try {
              steelsOutputOrder.setMakeDate(dateProvider.getCurrentTime());
              super.sendMessage("wms",steelsInputOrder,"insertSteelsOutputOrder",null);
          } catch (Exception e) {
              logger.error("error",e);
              return  false ;
          }
      }
  }

        return  flag ;
    }


}
